package test.ted.com.androidplugin2

import android.content.Context
import android.content.pm.PackageManager
import cn.ted.pluginlib.contract.TestPlugin
import dalvik.system.PathClassLoader


/**
 * Created by sfshine on 18-6-5.
 */
const val PLUGIN_PKG = "test.ted.com.sdkplugin"
const val CLASS_NAME = "test.ted.com.sdkplugin.TestPluginImpl"

public class HostManager {
    //    public fun getTestPlugin(context: Context): TestPlugin? {
//        val mmsCtx = context.createPackageContext("test.ted.com.sdkplugin",
//                Context.CONTEXT_INCLUDE_CODE or Context.CONTEXT_IGNORE_SECURITY)
//        val clazz = Class.forName("test.ted.com.sdkplugin.TestPluginImpl", true, mmsCtx.classLoader)
//        val constructor: Constructor<*>? = clazz.declaredConstructors.first { it.genericExceptionTypes.isEmpty() }
//        if (constructor != null) {
//            constructor.isAccessible = true
//            val obj = constructor.newInstance()
//            return obj as TestPlugin
//        }
//        return null
//    }
    /**
     *创建类加载器，把dex加载到虚拟机中
     *第一个参数：是指定apk安装的路径，这个路径要注意只能是通过actInfo.applicationInfo.sourceDir来获取
     *第二个参数：是C/C++依赖的本地库文件目录,可以为null
     *第三个参数：是上一级的类加载器*
     */
    fun getTestPlugin(context: Context): TestPlugin? {
        var dynamic: Class<*>
        /** 使用PathClassLoader方法加载类  */
        val apps = context.packageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES)
        // 获得指定包名的applicationInfo的信息
        val applicationInfo = apps.firstOrNull { it.packageName == PLUGIN_PKG }
        if (applicationInfo != null) {
            val sourceDir = applicationInfo.sourceDir
            val libPath = applicationInfo.nativeLibraryDir
            println("sourceDir: $sourceDir")
            println("libPath: $libPath")
            val pcl = PathClassLoader(sourceDir, libPath, context.classLoader)
            dynamic = pcl.loadClass(CLASS_NAME)
            return dynamic.newInstance() as TestPlugin
        } else {
            println("applicationInfo = null")
        }
        return null
    }

}